package com.na.game.opengl;

import java.util.ArrayList;
import java.util.List;

import javax.microedition.khronos.opengles.GL10;

import android.graphics.Rect;

import com.na.game.util.GameConfig;

public class GLPaint {

	protected static class AtomicPaint {
		protected int color;
		protected int vertexCount;
		protected GLShortBuffer vertexPointer;
		protected GLTexture texture;
		protected GLFloatBuffer texturePointer;
		protected boolean isLine;
		
		protected AtomicPaint(int color, int vertexCount, GLShortBuffer vertexPointer, boolean isLine) {
			this(color, vertexCount, vertexPointer, null, null, isLine);
		}
		
		protected AtomicPaint(int color, int vertexCount, GLShortBuffer vertexPointer, GLTexture texture, GLFloatBuffer texturePointer) {
			this(color, vertexCount, vertexPointer, texture, texturePointer, false);
		}
		
		private AtomicPaint(int color, int vertexCount, GLShortBuffer vertexPointer, GLTexture texture, GLFloatBuffer texturePointer, boolean isLine) {
			this.color = color;
			this.vertexCount = vertexCount;
			this.vertexPointer = vertexPointer;
			this.texture = texture;
			this.texturePointer = texturePointer;
			this.isLine = isLine;
		}
		
		protected void draw(GL10 gl) {
			setColor(gl, color);
			if (texture != null) {
				gl.glEnable(GL10.GL_TEXTURE_2D);
				texture.bind(gl);
				gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, texturePointer.getBuffer());
			} else {
				gl.glDisable(GL10.GL_TEXTURE_2D);
			}
			gl.glVertexPointer(2, GL10.GL_SHORT, 0, vertexPointer.getBuffer());
			if (isLine) {
				gl.glDrawArrays(GL10.GL_LINE_STRIP, 0, vertexCount);
			} else {
				gl.glDrawArrays(GL10.GL_TRIANGLES, 0, vertexCount);
			}
		}
		
		protected void setColor(GL10 gl, int color) {
			int a = color >> 24 & 0xFF;
			int r = color >> 16 & 0xFF;
			int g = color >> 8 & 0xFF;
			int b = color & 0xFF;
			gl.glColor4f(r / 255f, g / 255f, b / 255f, a / 255f);
		}
		
		protected void clear() {
			GLBufferManager.release(vertexPointer);
			if (texturePointer != null)
				GLBufferManager.release(texturePointer);
		}
	}
	
	protected Rect clip; // null:全屏
	protected List<AtomicPaint> paints;
	protected float scale = 1f;
	protected float tx, ty;
	
	protected GLPaint() {
		paints = new ArrayList<AtomicPaint>();
	}
	
	protected void setClip(Rect clip) {
		this.clip = clip;
	}
	
	protected Rect getClip() {
		return clip;
	}
	
	protected void setScale(float scale) {
		this.scale = scale;
	}
	
	protected void setTranslate(float tx, float ty) {
		this.tx = tx;
		this.ty = ty;
	}
	
	protected boolean isEmpty() {
		return paints.size() == 0;
	}
	
	protected void addAtomicPaint(AtomicPaint paint) {
		if (paint != null)
			paints.add(paint);
	}
	
	protected void draw(GL10 gl) {
		gl.glMatrixMode(GL10.GL_MODELVIEW);
		gl.glLoadIdentity();
		gl.glTranslatef(tx, -ty, 0f);
		gl.glScalef(scale, scale, 1f);
		gl.glMatrixMode(GL10.GL_PROJECTION);
		gl.glLoadIdentity();
		if (clip != null) {
			float left = clip.left * scale;
			float right = clip.right * scale;
			float top = clip.top * scale;
			float bottom = clip.bottom *  scale;
			
			float ol = left + tx;
			float or = right + tx;
			float ob = -bottom - ty;
			float ot = -top - ty;
			gl.glOrthof(ol, or, ob, ot, 1, -1);
			
			int x = (int) (tx + left);
			int y = (int) (-bottom - ty + GameConfig.screenHeight);
			int w = (int) (clip.width() * scale);
			int h = (int) (clip.height() * scale);
			gl.glViewport(x, y, w, h);
		} else {
			gl.glOrthof(0, GameConfig.screenWidth, -GameConfig.screenHeight, 0, 1, -1);
			gl.glViewport(0, 0, GameConfig.screenWidth, GameConfig.screenHeight);
		}
		
		int size = paints.size();
		for (int i = 0; i < size; i++) {
			paints.get(i).draw(gl);
		}
	}
	
	protected void clear() {
		for (int i = paints.size() - 1; i >= 0; i--) {
			paints.get(i).clear();
		}
		paints.clear();
	}
	
}
